import java.awt.Color;
import java.awt.Graphics;

import javax.sound.midi.ControllerEventListener;
import javax.sound.midi.MidiEvent;
import javax.sound.midi.MidiSystem;
import javax.sound.midi.MidiUnavailableException;
import javax.sound.midi.Sequencer;
import javax.sound.midi.ShortMessage;
import javax.swing.JFrame;
import javax.swing.JPanel;

import Controllers.ControllerVue;
import Lecteurs.Lecteur;
import Lecteurs.LecteurGenerateur;
import Lecteurs.LecteurGenerique;
import Lecteurs.LecteurMidi;
import Lecteurs.LecteurObservable;
import SequencerStrategies.SequencerStrategie1;
import Vue.Panneau;

// ce programme joue une musique al�atoire,et affiche des rectangles pleins, en rythme.

public class MidiExemple {

	static JFrame f = new JFrame("Mon nouveau clip vid�o");
	static MonPanneau ml;

	public static void main(String[] args) {
		/*MidiExemple mini = new MidiExemple();
		mini.go();*/
		
		LecteurGenerique lect = new LecteurMidi("ressources/gershwin_rhapsody_in_blue_c_oguri.mid");

		LecteurGenerique lect1 = new LecteurGenerateur(new SequencerStrategie1());

		LecteurObservable lectObservable = new LecteurObservable(lect);
		Sequencer sequenceur=null;
		try {
			sequenceur = MidiSystem.getSequencer();  //Recuperation du sequenceur par default 
			sequenceur.open();
		} catch (MidiUnavailableException e) {
			// TODO Auto-generated catch block
			System.out.println(e.getMessage());
		}
		ControllerVue controller = new ControllerVue(lectObservable,sequenceur);
		new Panneau(controller,lectObservable);
		//Appel du lecteur de fichier midi 
		lectObservable.sequencer(sequenceur);
		lectObservable.play(sequenceur);
				
		//Appel du lecteur de generation aleatoir 
		
		try {
			Thread.sleep(10000);
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}	
		lectObservable.stop(sequenceur);
		lect1.sequencer(sequenceur);
		lect1.play(sequenceur);
	}

	public void go() {

		//installerIHM();

		/*
		 * Le processus comprend 5 �tapes
		 * 1 - Obtenir un s�quenceur, un objet Sequencer, et l�ouvrir
		 * 2 - Cr�er un nouvel objet Sequence
		 * 3 - Demander � la Sequence de cr�er une piste piste de type Track
		 * 4 - Remplir la piste d��v�nements MIDI � MidiEvents � et transmettre la s�quence au s�quenceur
		 * 5 - D�marrer le s�quenceur avec la m�thode start() 
		 */

		/*try {

			// cr�er (et ouvrir) un s�quenceur
			Sequencer sequenceur = MidiSystem.getSequencer();
			sequenceur.open();

			// cr�er une s�quence et une piste
			Sequence seq = new Sequence(Sequence.PPQ, 4);
			Track piste = seq.createTrack();

			// maintenant cr�er deux �v�nements midi (contenant un message midi)
			int r = 0;
			for (int i = 0; i < 100; i+= 4) {

				r = (int) ((Math.random() * 50) + 1);
				
				// ajouter les �v�nements � la piste
				
				// 144 = noteOn, 1 = piano, 44 = la note, 100 = v�locit�
				piste.add(makeEvent(144,1,r,100,i));
				
				/* Pour suivre le rythme. Nous ins�rons notre PROPRE ControllerEvent :
				 * 176 indique que le type de l'�v�nement est ControllerEvent) 
				 * avec un argument pour le num�ro d'�v�nement, 127. 
				 * Cet �v�nement ne fera RIEN ! 
				 * Il n'est l� QUE pour que nous ayons un �v�nement chaque fois qu'une note est jou�e. 
				 * Autrement dit, sa seule raison d'�tre est qu'un �v�nement se d�clenche 
				 * que NOUS puissions �couter (impossible d'�couter NOTE ON/OFF ). 
				 * Cet �v�nement a lieu sur le M�ME temps que NOTE ON. 
				 *
				piste.add(makeEvent(176,1,127,0,i));
				
				// 128 = noteOff				
				piste.add(makeEvent(128,1,r,100,i + 2));
				
			} // fin de la boucle

		
			// ajouter la s�quence au s�quenceur, fixer le timing et d�marrer
			sequenceur.setSequence(seq);
			sequenceur.setTempoInBPM(120);
			sequenceur.start();
			
			/* le panneau de dessin (�couteur) doit s'enregistrer aupr�s du s�quenceur. 
			 * La m�thode d'enregistrement accepte l'�couteur 
			 * ET un tableau d'entiers repr�sentant la liste d'�v�nements voulus. 
			 * Ici, nous n'en voulons qu'un, le N� 127.
			 *
			sequenceur.addControllerEventListener(ml, new int[] {127});
			
		} catch (Exception ex) {ex.printStackTrace();}*/
	} // fin de la m�thode go()

	public MidiEvent makeEvent(int comd, int can, int un, int deux, int tic) {
		MidiEvent evenement = null;
		try {
			ShortMessage a = new ShortMessage();
			a.setMessage(comd, can, un, deux);
			evenement = new MidiEvent(a, tic);

		}catch(Exception e) { }
		return evenement;
	}

	public  void installerIHM() {
		ml = new MonPanneau();
		f.setContentPane(ml);
		f.setBounds(30,30, 300,300);
		f.setVisible(true);
	}


	/* le panneau de dessin va �couter les ControllerEvents
	 * et donc doit impl�menter l'interface �couteur
	 */
	@SuppressWarnings("serial")
	class MonPanneau extends JPanel implements ControllerEventListener {

		// nous ne voulons d'images que si nous avons un �v�nement
		boolean msg = false;

		public void controlChange(ShortMessage evenement) {
			msg = true;
			repaint();
		}

		public void paintComponent(Graphics g) {
			if (msg) {

				int r = (int) (Math.random() * 250);
				int gr = (int) (Math.random() * 250);
				int b = (int) (Math.random() * 250);

				g.setColor(new Color(r,gr,b));

				int ht = (int) ((Math.random() * 120) + 10);
				int width = (int) ((Math.random() * 120) + 10);

				int x = (int) ((Math.random() * 40) + 10);
				int y = (int) ((Math.random() * 40) + 10);

				g.fillRect(x,y,ht, width);
				msg = false;
			} 
		} 
	}  
} 

